package net.bytebuddy.dynamic;
import net.bytebuddy.agent.ByteBuddyAgent;
import net.bytebuddy.dynamic.loading.ClassReloadingStrategy;
import net.bytebuddy.test.utility.AgentAttachmentRule;
import net.bytebuddy.test.utility.JavaVersionRule;
import net.bytebuddy.test.utility.ObjectPropertyAssertion;
import org.hamcrest.CoreMatchers;
import org.junit.Ignore;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.MethodRule;
import java.lang.instrument.Instrumentation;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.security.AccessControlContext;
import java.security.AccessController;
import java.security.ProtectionDomain;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Iterator;
import static org.hamcrest.CoreMatchers.*;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
public class ClassFileLocatorAgentBasedTest {
private static final String FOO = "foo";
@Rule
public MethodRule agentAttachmentRule = new AgentAttachmentRule();
public MethodRule javaVersionRule = new JavaVersionRule();
@Test
@AgentAttachmentRule.Enforce(redefinesClasses = true)
public void testStrategyCreation() throws Exception {
assertThat(ByteBuddyAgent.install(), instanceOf(Instrumentation.class));
assertThat(ClassReloadingStrategy.fromInstalledAgent(), notNullValue());
}
@Test
@AgentAttachmentRule.Enforce(retransformsClasses = true)
public void testExtraction() throws Exception {
assertThat(ByteBuddyAgent.install(), instanceOf(Instrumentation.class));
ClassFileLocator classFileLocator = ClassFileLocator.AgentBased.fromInstalledAgent(getClass().getClassLoader());
ClassFileLocator.Resolution resolution = classFileLocator.locate(Foo.class.getName());
assertThat(resolution.isResolved(), is(true));
assertThat(resolution.resolve(), notNullValue(byte[].class));
}
@Test
@AgentAttachmentRule.Enforce(retransformsClasses = true)
public void testExtractionOfInflatedMethodAccessor() throws Exception {
assertThat(ByteBuddyAgent.install(), instanceOf(Instrumentation.class));
Method bar = Foo.class.getDeclaredMethod("bar");
for (int i = 0; i < 20; i++) {
bar.invoke(new Foo());
}
Field field = Method.class.getDeclaredField("methodAccessor");
field.setAccessible(true);
Object methodAccessor = field.get(bar);
Field delegate = methodAccessor.getClass().getDeclaredField("delegate");
delegate.setAccessible(true);
Class<?> delegateClass = delegate.get(methodAccessor).getClass();
ClassFileLocator classFileLocator = ClassFileLocator.AgentBased.fromInstalledAgent(delegateClass.getClassLoader());
ClassFileLocator.Resolution resolution = classFileLocator.locate(delegateClass.getName());
assertThat(resolution.isResolved(), is(true));
assertThat(resolution.resolve(), notNullValue(byte[].class));
}
@Test
public void testExplicitLookupBootstrapClassLoader() throws Exception {
ClassFileLocator.AgentBased.ClassLoadingDelegate classLoadingDelegate = ClassFileLocator.AgentBased.ClassLoadingDelegate.Explicit.of(Object.class);
assertThat(classLoadingDelegate.getClassLoader(), is(ClassLoader.getSystemClassLoader()));
assertThat(classLoadingDelegate.locate(Object.class.getName()), CoreMatchers.<Class<?>>is(Object.class));
assertThat(classLoadingDelegate.locate(String.class.getName()), CoreMatchers.<Class<?>>is(String.class));
}
@Test
public void testExplicitLookup() throws Exception {
ClassFileLocator.AgentBased.ClassLoadingDelegate classLoadingDelegate = ClassFileLocator.AgentBased.ClassLoadingDelegate.Explicit.of(Foo.class);
assertThat(classLoadingDelegate.getClassLoader(), is(Foo.class.getClassLoader()));
assertThat(classLoadingDelegate.locate(Foo.class.getName()), CoreMatchers.<Class<?>>is(Foo.class));
assertThat(classLoadingDelegate.locate(Object.class.getName()), CoreMatchers.<Class<?>>is(Object.class));
}
@Test
public void testExtractingTransformerHandlesNullValue() throws Exception {
assertThat(new ClassFileLocator.AgentBased.ExtractionClassFileTransformer(mock(ClassLoader.class), FOO).transform(mock(ClassLoader.class),
FOO,
Object.class,
mock(ProtectionDomain.class),
new byte[0]), nullValue(byte[].class));
}
@Test
public void testObjectProperties() throws Exception {
ObjectPropertyAssertion.of(ClassFileLocator.AgentBased.class).refine(new ObjectPropertyAssertion.Refinement<Instrumentation>() {
@Override
public void apply(Instrumentation mock) {
when(mock.isRetransformClassesSupported()).thenReturn(true);
}
}).apply();
ObjectPropertyAssertion.of(ClassFileLocator.AgentBased.ClassLoadingDelegate.Default.class).apply();
ObjectPropertyAssertion.of(ClassFileLocator.AgentBased.ClassLoadingDelegate.ForDelegatingClassLoader.class).apply();
final Iterator<Field> iterator = Arrays.asList(Foo.class.getDeclaredFields()).iterator();
ObjectPropertyAssertion.of(ClassFileLocator.AgentBased.ClassLoadingDelegate.ForDelegatingClassLoader.Dispatcher.Resolved.class)
.create(new ObjectPropertyAssertion.Creator<Field>() {
@Override
public Field create() {
return iterator.next();
}
})
.apply();
ObjectPropertyAssertion.of(ClassFileLocator.AgentBased.ClassLoadingDelegate.ForDelegatingClassLoader.Dispatcher.Unresolved.class).apply();
final Iterator<Class<?>> otherIterator = Arrays.<Class<?>>asList(Integer.class, String.class, Object.class, Byte.class).iterator();
ObjectPropertyAssertion.of(ClassFileLocator.AgentBased.ClassLoadingDelegate.Explicit.class).create(new ObjectPropertyAssertion.Creator<Collection<Class<?>>>() {
@Override
public Collection<Class<?>> create() {
return Collections.<Class<?>>singletonList(otherIterator.next());
}
}).apply();
ObjectPropertyAssertion.of(ClassFileLocator.AgentBased.ClassLoadingDelegate.ForDelegatingClassLoader.Dispatcher.CreationAction.class).apply();
}
@Test(expected = IllegalArgumentException.class)
public void testNonCompatible() throws Exception {
new ClassFileLocator.AgentBased(mock(Instrumentation.class), getClass().getClassLoader());
}
private static class Foo {
int foo, bar;
void bar() {
}
}
}